package com.ib;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ib.handler.ServerHandler;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class Server {
	
	private static final Logger LOG = LoggerFactory.getLogger(Server.class);
	
	private Integer port;
	
	public Server() {
		super();
	}

	public Server(Integer port) {
		super();
		this.port = port;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new Server(Integer.valueOf(args[0])).run();
	}
	
	public void run() {
		if(this.port == null) {
			throw new NullPointerException("The port is null");
		}
		String osName = System.getProperty("os.name");
		LOG.info("The system is {}",osName);
		EventLoopGroup bossGroup = null;
		EventLoopGroup workGroup = null;
		if (osName.equals("Linux")) {
			bossGroup = new EpollEventLoopGroup();
			workGroup = new EpollEventLoopGroup();
		} else {
			bossGroup = new NioEventLoopGroup(); // 接收消息循环队列
			workGroup = new NioEventLoopGroup(); // 发送消息循环队列
		}
		try {
			ServerBootstrap bootstrap = new ServerBootstrap();
			bootstrap.group(bossGroup, workGroup) // 加载消息循环队列
			
			   //keepAlive默认是打开
            //.option(ChannelOption.SO_KEEPALIVE, true)
            // 默认采用AdaptiveRecvByteBufAllocator分配器，不需要配置
            //.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT)
            //PooledByteBufAllocator这种分配器是默认分配器，当buffer被写入下一个节点的时候，它会
            //自动释放，并放入pool里面
            //.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
            .option(ChannelOption.SO_BACKLOG, 100)
            .handler(new LoggingHandler(LogLevel.INFO))
            //.option(ChannelOption.SO_SNDBUF, 1024*256) //发包缓冲区，单位多少？
            .option(ChannelOption.SO_RCVBUF, 1024*256); //收包换成区，单位多少？
            //.option(ChannelOption.TCP_NODELAY, true); //TCP立即发包
			
			if (osName.equals("Linux")) { //Linux平台用Epoll模式
		        bootstrap.channel(EpollServerSocketChannel.class);
		    } else {
		        bootstrap.channel(NioServerSocketChannel.class);

		    }
			bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
						protected void initChannel(SocketChannel socketChannel) throws Exception {
							ChannelPipeline p = socketChannel.pipeline();
							//p.addLast(new IdleStateHandler(25, 15, 10,TimeUnit.SECONDS));
							// p.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, -4, 0));
							//p.addLast(new MsgPackDecode()); // Netty4自带的String解码器-->StringDecoder
							p.addLast(new StringDecoder()); 
							p.addLast(new StringEncoder()); 
							//p.addLast(new MsgPackEncode()); // Netty4自带的String编码器-->StringEncoder
							p.addLast(new ServerHandler()); //SimpleChannelInboundHandler
						}
					});

			Channel ch = bootstrap.bind(port).sync().channel();

			LOG.info("------Server startup success------");

			ch.closeFuture().sync();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			bossGroup.shutdownGracefully();
			workGroup.shutdownGracefully();
		}
	}
}
